package com.easyaop.asm.bytecode.asm;

import com.easyaop.asm.bytecode.MethodInfo;
import lombok.Setter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;

import java.lang.reflect.Modifier;

public class JoinMethodVisitor extends MethodVisitor implements Opcodes {
    @Setter
    private MethodInfo target;
    @Setter
    private Integer jpPos;
    @Setter
    private int offSet;// 把切面变量的位置，偏移下

    public JoinMethodVisitor(int api, MethodVisitor methodVisitor) {
        super(api, methodVisitor);
    }

    @Override
    public void visitCode() {
        super.visitCode();

//        offset+num
//        num是aop方法里的位置，offsize是需要偏移的大小
//        visitInsn(ACONST_NULL);
//        visitVarInsn(ASTORE, offSet + 0/*call*/);

        if (Modifier.isStatic(target.access)) {
            visitInsn(ACONST_NULL);// 链接static 方法的target，默认就null吧，Class对象从joinpoint里取
            visitVarInsn(ASTORE, offSet + 1/*target*/);
        }

        GeneratorAdapter targetAdapter = new GeneratorAdapter(mv, target.access, target.name, target.descriptor);
        targetAdapter.loadArgArray();
        visitVarInsn(ASTORE, offSet + 2/*args*/);

        if (jpPos == null) {
            visitInsn(ACONST_NULL);
        } else {
            visitIntInsn(SIPUSH, jpPos);
            visitMethodInsn(INVOKESTATIC, "com/easyaop/asm/bytecode/Context", "getJoinPoint", "(I)Lcom/easyaop/api/join/JoinPoint;", false);
        }
        visitVarInsn(ASTORE, offSet + 3/*joinpoint*/);

        visitInsn(ACONST_NULL);
        visitVarInsn(ASTORE, offSet + 4/*call*/);
    }

    @Override
    public void visitVarInsn(int opcode, int varIndex) {
        if ((!Modifier.isStatic(target.access)) && varIndex == offSet + 1) {
            varIndex = 0;//如果是非static方法， 把target的存取 转换成this（位置0）
        }
        super.visitVarInsn(opcode, varIndex);
    }
}
